//least update 2015-3-30
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> 
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>   
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#include "./mtd/mtd-user.h"
#include "./include/os_struct.h"

#define BUF_SIZE 			512
#define SERVICE_READY 		220
#define NEED_PASSWORD 		331
#define LOGIN_SUCS 			230
#define CONTROL_CLOSE		221
#define PATHNAME_CREATE 	257
#define PASV_MODE 			227
#define NO_SUCH_FILE 		550 
#define DOWN_READY   		125

#define QUIT 				7
#define MAX146  			8
#define SZ_256				256
#define SZ_600				600

static struct sockaddr_in server; 		// 控制连接的socket
static char   user[20] = "administrator"; // 用户名
static char   pass[20] = "windows";      	// 密码
static char   filepath[250] = "windows";  // FILEPATH  
static char   newfilename[SZ_256];
static int    data_port;              		// 数据连接端口
static int    data_sock;
volatile unsigned short data_packet_num;
static unsigned char data_packet_idex[12];
unsigned char data_packet[60][520];
unsigned char file_version[10];

unsigned char update_frames[12];
unsigned char update_status[12];
unsigned char update_frames_stats[12];
unsigned char update_frames_trays[12][6];
unsigned char update_trays_stats[12][6];
extern int	  uart0fd;
extern OS_BOARD s3c44b0x;
extern OS_UART  uart0;
extern volatile unsigned char deviceUpdate;


// 报错
static void errorReport(unsigned char err_info)
{
	unsigned char data[6];

	memset(data,err_info,sizeof(data));
}

// 发送命令，参数为 socket号 、 命令标示 和 命令参数
static void sendCommand(int sock_fd, const char* cmd, const char* info)
{
    char buf[BUF_SIZE] = {0};

    strcpy(buf, cmd);
    strcat(buf, info);
    strcat(buf, "\r\n");
    if (send(sock_fd, buf, strlen(buf), 0) < 0){
        errorReport(1);
	}
}

// 控制连接获取服务器应答，返回应答码
static int getReplyCode(int sockfd)
{
    int r_code, bytes;
    char buf[BUF_SIZE] = {0}, nbuf[5] = {0};

    if ((bytes = read(sockfd, buf, BUF_SIZE - 2)) > 0) {
        r_code = atoi(buf);
        buf[bytes] = '\0';
    }else{
        return -1;
	}

    if (buf[3] == '-') {
        char* newline = strchr(buf, '\n');
        if (*(newline+1) == '\0') {
            while ((bytes = read(sockfd, buf, BUF_SIZE - 2)) > 0) {
                buf[bytes] = '\0';
                if (atoi(buf) == r_code)
                    break;
            }
        }
    }

    if (r_code == PASV_MODE){
        char* begin = strrchr(buf, ',')+1;
        char* end = strrchr(buf, ')');
        strncpy(nbuf, begin, end - begin);
        nbuf[end-begin] = '\0';
        data_port = atoi(nbuf);
        buf[begin-1-buf] = '\0';
        end = begin - 1;
        begin = strrchr(buf, ',')+1;
        strncpy(nbuf, begin, end - begin);
        nbuf[end-begin] = '\0';
        data_port += 256 * atoi(nbuf);
    }

    return r_code;
}

// 连接到服务器，参数为 IP地址 和 端口号，返回是否连接成功的编号
static int connectToHost(unsigned char* ip, unsigned char* pt)
{
    int sockfd = 0, port = 0;

	port = pt[0]*100 + pt[1];
    if(port <= 0 || port >= 65536)
        errorReport(2);

    server.sin_family = AF_INET;
    server.sin_port   = htons(port);
	server.sin_addr.s_addr =  *(ip+3)<<24 | *(ip+2)<<16 | *(ip+1)<<8 | *(ip+0);

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        errorReport(3);
    if(connect(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0)
        errorReport(4);
    
	return sockfd;
}

// 用户登录
static int userLogin(int sockfd)
{
    sendCommand(sockfd, "USER ", user);
    if(getReplyCode(sockfd) == NEED_PASSWORD)
	{
        sendCommand(sockfd, "PASS ", pass);
        if(getReplyCode(sockfd) != LOGIN_SUCS)
		{ //login success!
            return -1;
        }else{
            return 0;
        }
    }else{
        return -1;
    }
}


static void split_filename(unsigned char *file,int len)
{
	int i = len,j = 0;
	char version[20];
	unsigned char idex = 0;

	for(;i > 0;i--){
		if(*(file+i) == 0x5c)
			break;
	}

	memset(newfilename,0,sizeof(newfilename));
	strncpy(&newfilename[0],&file[0] + i + 1,len-(i-1));
	strncpy(&version[0],&file[0] + i + 1,len-(i-1));
	newfilename[len-i+1] = '\0';

	idex = 0;
	memset(file_version,0,sizeof(file_version));
	for(j = 0;j < len-i+1;j++){
		if(version[j] == 0x5f){//5f:is symbol for _
			file_version[idex++] = version[j+1]-0x30;
			file_version[idex++] = version[j+2]-0x30;
		}
	}
	

}

// 下载服务器的一个文件
static int cmd_get(int fd, char* cmd,unsigned char *src)
{
    int i = 0, bytes = 0;
	char filename[SZ_256];
	unsigned char buf[520];
	unsigned char packetnums = 0x0;

	data_port = 0;
	data_sock = -1;
    sendCommand(fd, "PASV", "");
    if (getReplyCode(fd) != PASV_MODE){
        return 0;
    }

    server.sin_port = htons(data_port);
    if((data_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        errorReport(5);
	}

    if(connect(data_sock, (struct sockaddr*)&server, sizeof(server)) < 0){
        errorReport(6);
	}

    sendCommand(fd, "TYPE ", "I");
    getReplyCode(fd);

	if(src[347] == 0x01){
		sendCommand(fd, "CWD ", "ODF");
	    getReplyCode(fd);
	    sendCommand(fd, "CWD ", "44b0");
	    getReplyCode(fd);	
	}else if(src[347] == 0x02){
		sendCommand(fd, "CWD ", "ODF");
	    getReplyCode(fd);
	    sendCommand(fd, "CWD ", "146");
	    getReplyCode(fd);
	}else if(src[347] == 0x03){
		sendCommand(fd, "CWD ", "ODF");
	    getReplyCode(fd);
	    sendCommand(fd, "CWD ", "410");
	    getReplyCode(fd);
	}

	strcpy(filename,cmd);
    sendCommand(fd, "RETR ",filename);
	if(getReplyCode(fd) != DOWN_READY){
        errorReport(7);
        close(fd);
        return 0;
	}

	if(src[347] == 0x01){
		return 0;
	}

	memset(buf,0xff,sizeof(buf));
	data_packet_num = 0;
	packetnums = 0;
	for(i = 0; i < 60;i++){
		memset(&data_packet[i],0xff,520);
	}

    while((bytes = read(data_sock, buf, BUF_SIZE)) > 0){
		memcpy(&data_packet[packetnums][0],buf,BUF_SIZE);	
		packetnums += 1;	
		memset(buf,0xff,sizeof(buf));
		data_packet_num++;
		usleep(50000);
	}
	
    close(data_sock);
	
	return 0;
}

// 退出
static void cmd_quit(int fd)
{
    sendCommand(fd, "QUIT", "");
    if (getReplyCode(fd) == CONTROL_CLOSE)
	{

	}
}


// 运行客户端 
static int run(unsigned char *username,unsigned char *passwd,
		unsigned char* ip, unsigned char* pt,unsigned char *path,unsigned char *src)
{
	int control_sockfd = 0, rc = 0;
	int filepath_len = *(path+0) <<8 | *(path+1);

	memset(user,0,sizeof(user));
	memset(pass,0,sizeof(pass));
	memset(filepath,0,sizeof(filepath));

	strncpy(user,&username[0]+1,*(username+0));
	strncpy(pass,&passwd[0]+1,*(passwd+0));
	strncpy(filepath,&path[0]+2,filepath_len);
	split_filename(path,filepath_len);

	control_sockfd = connectToHost(ip, pt); 
    if(getReplyCode(control_sockfd) != SERVICE_READY){
        errorReport(9);
		rc = 1;
	}

    while(userLogin(control_sockfd) != 0);
   
	rc = cmd_get(control_sockfd,newfilename,src);
	if(src[347] == 0x01){
		/* don't close control_sockfd,because we need transfer data before close */
		return rc;
	}
	cmd_quit(control_sockfd);
    close(control_sockfd);

	return rc;
}

static int isArrayEmpty(unsigned char *src,unsigned short len)
{
	unsigned int i = 0;
	
	if(src == NULL)
		return 0;

	for(;i < len; i++){
		if(*(src+i) != 0x0)break;	
	}	
	if(i == len)
		return 1;
	else 
		return 0;	
	
}

static int order_tasks_to_sim3u146_board(void)
{
	unsigned short TaskFrameDataLength = 0,nBytes = 0;
	unsigned char  TaskPorts[24] = {'\0'};
	unsigned char  i = 0,j = 0;

	for(;i < s3c44b0x.frameNums;i++){
		if(uart0.txBuf[i][3] != 0x0)TaskPorts[i] = 1;
	}

	for(;j < 3;j++){//重发机制，3次

		for(i = 0; i < s3c44b0x.frameNums;i++){
			if(TaskPorts[i] == 1){
				TaskFrameDataLength = uart0.txBuf[i][1] << 8| uart0.txBuf[i][2] + 2;
				write(uart0fd,&uart0.txBuf[i][0],TaskFrameDataLength);
				memset(uart0.rxBuf,0,sizeof(uart0.rxBuf));
				usleep(200000);
				nBytes = read(uart0fd,uart0.rxBuf,100);
				if(nBytes > 0){
					if(uart0.rxBuf[3] == 0xa6){
						TaskPorts[i] = 0x0;
						memset(&uart0.txBuf[i][0],0,SZ_600);
					}
				}
			}
		}
	}

	if(isArrayEmpty(TaskPorts,24) == 1){
		return 1;
	}else{
		return 0;
	}
} 

void update_cf8051(unsigned char dt,unsigned char *src,int fd)
{
	static unsigned char results[600];
	static int clientfd = 0;
	unsigned short record_idex = 0,end_idex = 0,i = 0,c_idex = 0;
	unsigned char  frameidex = 0,traynum = 0,num = 0,packet_num = 0;
	unsigned char  index[12],trayval = 0,j = 0,update_continue = 0;
	int retval = 0;

	switch(dt){
	case 3:	
		/* 1-1-0 :webmaster send update cf8051 command,here */
		clientfd = fd;
		memset(update_frames,0,sizeof(update_frames));
		memset(update_status,0xEE,sizeof(update_status));
		memset(data_packet_idex,0,sizeof(data_packet_idex));
		for(i = 0; i < 12; i++){
			memset(&update_frames_trays[i][0],0,6);
			memset(&update_trays_stats[i][0],0,6);
		}
		/* 1-1-1: set results val */
		memset(results,0,sizeof(results));
		results[0] = 0x7e;
		results[3] = 0x06;
		memcpy(&results[4],&src[4],17);
		results[21] = 0x03;//TYPE
		results[22] = src[348];//num
		for(i = 349;i < 349 + src[348]*2;i+=2){
			memcpy(&results[23+record_idex],&src[i],2);
			record_idex += 7;
			frameidex = src[i];
			traynum = src[i+1];
			update_frames[frameidex-1] = 1;
			update_frames_trays[frameidex-1][traynum-1]	= 1;	
			update_trays_stats[frameidex-1][traynum-1]	= 0;	
		}

		/*1-1-2:download file from FTP Server*/
		retval = run(&src[285],&src[316],&src[21],&src[25],&src[27],src);
		end_idex = 23 + record_idex;
		record_idex = 0;
		for(i = 349;i < 349 + src[348]*2;i+=2){
			results[25+record_idex] = 0xee;
			memcpy(&results[26+record_idex],file_version,4);
			record_idex += 7;
		}
		results[1] = (end_idex) >> 8 & 0xff;
		results[2] = (end_idex) & 0xff;
		results[end_idex] = crc8(results,end_idex);
		results[end_idex+1] = 0x5a;
		if(retval == 0x01){
			/* download fail*/
			goto update_error;
		}	

		/* 1-2-1 orginal data to sim3u146 board */
		memset(index,0,sizeof(index));
		for(i = 0;i < 12;i++)
		{
			if(update_frames[i] > 0)
			{/*if this frame's tray need to update*/
				memset(&uart0.txBuf[i][0],0,SZ_600);
				num = 1;
				for(trayval = 0; trayval < 6;trayval++)
				{/*check how many tray need to update*/
					if(update_frames_trays[i][trayval] > 0)
					{
						if(index[i] > 8)
						{/*if this frame already filing data,so fresh data should be added at the tail*/
							c_idex = index[i];
							uart0.txBuf[i][6] = num++;//total update cf8051 boards num
							uart0.txBuf[i][c_idex] = i+1;//frameidex 
							uart0.txBuf[i][c_idex+1] = trayval+1;//traynum
							uart0.txBuf[i][c_idex+2] = 0x01;//startup success || startup fail				
							index[i] += 3;
						}else
						{/*if this frame without data filling ,so orginize new data */
							uart0.txBuf[i][0] = 0x7e;
							uart0.txBuf[i][3] = 0x06;
							uart0.txBuf[i][4] = 0x01;//startup
							uart0.txBuf[i][5] = 0x03;
							uart0.txBuf[i][6] = num++;//total update cf8051 boards num
							uart0.txBuf[i][7] = i+1;//frameidex 
							uart0.txBuf[i][8] = trayval+1;//traynum
							uart0.txBuf[i][9] = 0x01;//startup success || startup fail
							index[i] += 10; 
						}
					}
				}
			}
		}
		/** calc crc */
		for(i = 0;i < 12;i++){
			if(index[i] > 8){
				c_idex = index[i];
				uart0.txBuf[i][1] = 0x00;
				uart0.txBuf[i][2] = c_idex;
				uart0.txBuf[i][c_idex] = crc8(&uart0.txBuf[i][0],c_idex);
				uart0.txBuf[i][c_idex+1] = 0x5a;
			}
		}
		
		update_continue = 0x00;
		/* 1-2-1 send startup cmd to cf8051 */
		if(!order_tasks_to_sim3u146_board()){
			for(i = 0; i < 12; i++){
				if((update_frames[i] == 0x01) && (uart0.txBuf[i][3] != 0x0) ){
					memset(&uart0.txBuf[i][0],0,100);
					update_status[i] = 0x0;
				}else{
					update_continue = 0x1;
				}
			}
			if(update_continue == 0x00)
				goto update_error;
		}
		
		/* SET Update Flags */
		deviceUpdate = 0x01;
	break;
	case 2://data from uart
		switch(src[4]){
		case 0x01:
			frameidex = src[7];
			/* check this frame's startup results
			 * if failed,
			 * 		don't send any packet 
			 * else
			 * 		send packet*/
	
			if(deviceUpdate != 0x01)
				return;

			/*2-1-1:record every cf8051 board's startup  results*/
			for(i = 0,j = 9;i < 6;i++,j += 3){
				if(update_frames_trays[frameidex-1][i] == 1){
					update_trays_stats[frameidex-1][i] = src[j];//record startup stat
				}
			}
			
			/*2-1-2:if Failed all trays,check the other frames */
			update_continue = 0x0;
			for(i = 0; i < 12; i++){
				for(j = 0; j < 6; j++){
					if((update_frames_trays[i][j] == 1) && (update_trays_stats[i][j] == 0x0)){
						update_continue = 1;
						break;
					}
				}
				if(update_continue)
					break;
			}

			if(update_continue = 0x0)
				goto update_error; 

			update_continue = 0x0;
			/*2-1-3:check this trays in this frame startup success or not? */
			for(i = 0; i < 6; i++){
				if((update_frames_trays[frameidex-1][i] == 0x1) && (update_trays_stats[frameidex-1][i] == 0x0)){
					update_continue = 0x1;
					break;
				}
			}

			if(update_continue = 0x0)
				return; 

			/* send data packet*/
			uart0.txBuf[frameidex-1][0] = 0x7e;
			uart0.txBuf[frameidex-1][3] = 0x06;
			uart0.txBuf[frameidex-1][4] = 0x02;
			uart0.txBuf[frameidex-1][5] = 0x03;
			c_idex = 7;
			for(i = 0,j = 0;i < 6;i++){
				if(update_frames_trays[frameidex-1][i]){
					uart0.txBuf[frameidex-1][c_idex+j*3] = frameidex;
					uart0.txBuf[frameidex-1][c_idex+1+j*3] = i+1;
					uart0.txBuf[frameidex-1][c_idex+2+j*3] = 0x0;
					j++;
				}
			}
			c_idex = c_idex + j*3;
			uart0.txBuf[frameidex-1][6] = j;
			uart0.txBuf[frameidex-1][c_idex] = 0x00;
			uart0.txBuf[frameidex-1][c_idex+1] = 0x01;
			c_idex += 2;
			memcpy(&uart0.txBuf[frameidex-1][c_idex],&data_packet[0][0],512);
			c_idex += 512;
			uart0.txBuf[frameidex-1][1] = (c_idex>>8) & 0xff;
			uart0.txBuf[frameidex-1][2] = c_idex & 0xff;
			uart0.txBuf[frameidex-1][c_idex] = crc8(&uart0.txBuf[frameidex-1][0],c_idex);
			uart0.txBuf[frameidex-1][c_idex+1] = 0x5a;

			update_continue = 0x00;
			/* 1-2-1 send startup cmd to cf8051 */
			if(!order_tasks_to_sim3u146_board()){
				for(i = 0; i < 12; i++){
					if((update_frames[i] == 0x01) && (uart0.txBuf[i][3] != 0x0) ){
						memset(&uart0.txBuf[i][0],0,100);
						update_status[i] = 0x0;
					}else{
						update_continue = 0x1;
					}
				}
				if(update_continue == 0x00)
					goto update_error;
			}

		break;
		case 0x02:
			/*packet transfer now*/
			frameidex = src[7]; 
			/* check this frame's packet written results
			 * if failed,
			 * 		don't send any packet 
			 * else
			 * 		send packet*/

			/*2-1-1:record every cf8051 board's startup  results*/
			for(i = 0,j = 9;i < 6;i++,j += 3){
				if(update_frames_trays[frameidex-1][i] == 1){
					update_trays_stats[frameidex-1][i] = src[j];//record startup stat
				}
			}
			
			/*2-1-2:if Failed all trays,check the other frames */
			update_continue = 0x0;
			for(i = 0; i < 12; i++){
				for(j = 0; j < 6; j++){
					if((update_frames_trays[i][j] == 1) && (update_trays_stats[i][j] == 0x0)){
						update_continue = 1;
						break;
					}
				}
				if(update_continue)
					break;
			}

			if(update_continue = 0x0)
				goto update_error; 

			update_continue = 0x0;
			/*2-1-3:check this trays in this frame startup success or not? */
			for(i = 0; i < 6; i++){
				if((update_frames_trays[frameidex-1][i] == 0x1) && (update_trays_stats[frameidex-1][i] == 0x0)){
					update_continue = 0x1;
					break;
				}
			}

			if(update_continue = 0x0)
				return; 

			/*2-2-4: continue update cf8051 */
			packet_num = src[26];
			if(packet_num == data_packet_num ){
				/* send restart cmd */
				memset(&uart0.txBuf[frameidex-1][0],0,SZ_600);
				num = 1;
				index[frameidex-1] = 0x0;
				for(trayval = 0; trayval < 6;trayval++)
				{/*check how many tray need to update*/
					if(update_frames_trays[frameidex-1][trayval] > 0)
					{
						if(index[frameidex-1] > 8)
						{/*if this frame already filing data,so fresh data should be added at the tail*/
							c_idex = index[frameidex-1];
							uart0.txBuf[frameidex-1][6] = num++;//total update cf8051 boards num
							uart0.txBuf[frameidex-1][c_idex] = frameidex;//frameidex 
							uart0.txBuf[frameidex-1][c_idex+1] = trayval+1;//traynum
							uart0.txBuf[frameidex-1][c_idex+2] = 0x01;//startup success || startup fail				
							index[frameidex-1] += 3;
						}else
						{/*if this frame without data filling ,so orginize new data */
							uart0.txBuf[frameidex-1][0] = 0x7e;
							uart0.txBuf[frameidex-1][3] = 0x06;
							uart0.txBuf[frameidex-1][4] = 0x03;//restart
							uart0.txBuf[frameidex-1][5] = 0x03;
							uart0.txBuf[frameidex-1][6] = num++;//total update cf8051 boards num
							uart0.txBuf[frameidex-1][7] = frameidex;//frameidex 
							uart0.txBuf[frameidex-1][8] = trayval+1;//traynum
							uart0.txBuf[frameidex-1][9] = 0x01;//startup success || startup fail
							index[frameidex-1] = 10; 
						}
					}
				}

				if(index[frameidex-1] > 8){
					c_idex = index[frameidex-1];
					uart0.txBuf[frameidex-1][1] = 0x00;
					uart0.txBuf[frameidex-1][2] = c_idex;
					uart0.txBuf[frameidex-1][c_idex] = crc8(&uart0.txBuf[frameidex-1][0],c_idex);
					uart0.txBuf[frameidex-1][c_idex+1] = 0x5a;
				}
				
				update_continue = 0x00;
				/* 1-2-1 send startup cmd to cf8051 */
				if(!order_tasks_to_sim3u146_board()){
					for(i = 0; i < 12; i++){
						if((update_frames[i] == 0x01) && (uart0.txBuf[i][3] != 0x0) ){
							memset(&uart0.txBuf[i][0],0,100);
							update_status[i] = 0x0;
						}else{
							update_continue = 0x1;
						}
					}
					if(update_continue == 0x00)
						goto update_error;
				}

			}else{
				/* send data packet*/
				uart0.txBuf[frameidex-1][0] = 0x7e;
				uart0.txBuf[frameidex-1][3] = 0x06;
				uart0.txBuf[frameidex-1][4] = 0x02;
				uart0.txBuf[frameidex-1][5] = 0x03;
				c_idex = 7;
				for(i = 0,j = 0;i < 6;i++){
					if(update_frames_trays[frameidex-1][i]){
						uart0.txBuf[frameidex-1][c_idex+j*3] = frameidex;
						uart0.txBuf[frameidex-1][c_idex+1+j*3] = i+1;
						uart0.txBuf[frameidex-1][c_idex+2+j*3] = 0x0;
						j++;
					}
				}
				c_idex = c_idex + j*3;
				uart0.txBuf[frameidex-1][6] = j;
				uart0.txBuf[frameidex-1][c_idex] = 0x00;
				uart0.txBuf[frameidex-1][c_idex+1] = packet_num+1;
				c_idex += 2;
				memcpy(&uart0.txBuf[frameidex-1][c_idex],&data_packet[packet_num][0],512);
				c_idex += 512;
				uart0.txBuf[frameidex-1][1] = (c_idex>>8) & 0xff;
				uart0.txBuf[frameidex-1][2] = c_idex & 0xff;
				uart0.txBuf[frameidex-1][c_idex] = crc8(&uart0.txBuf[frameidex-1][0],c_idex);
				uart0.txBuf[frameidex-1][c_idex+1] = 0x5a; 

				update_continue = 0x00;
				/* 1-2-1 send startup cmd to cf8051 */
				if(!order_tasks_to_sim3u146_board()){
					for(i = 0; i < 12; i++){
						if((update_frames[i] == 0x01) && (uart0.txBuf[i][3] != 0x0) ){
							memset(&uart0.txBuf[i][0],0,100);
							update_status[i] = 0x0;
						}else{
							update_continue = 0x1;
						}
					}
					if(update_continue == 0x00)
						goto update_error;
				}

			}
		break;
		case 0x03:
			/* check which frame report its cf8051 board restart results */
			frameidex = src[7];
			for(i = 23;i < results[2];i += 7){
				if(results[i] == frameidex)
					break;
			}

			/* here,we record upstairs's cf8051 board restart results from
			 * Tray1~Tray6*/
			for(j = 0;j < 6;j++){
				if(src[9+j*3] == 0x00 || src[9+j*3] == 0x01){
					results[i+2] = src[9+j*3];
					i += 7;
				}
			}
			
			/* it means this board update finished */
			update_status[frameidex-1] = 0x01;

			/* 0x01:need update 0xEE:not update finished*/ 
			for(i = 0; i < 12; i++){
				if((update_frames[i] == 0x01) && (update_status[i] == 0xEE)){
					break;	
				}
			}
			
			if(i != 12)return;

		//	debug_net_printf(results,results[1]<<8|results[2]+2,60001);
			if(i > results[1]<<8|results[2]){
				c_idex = results[1]<<8|results[2];
				results[c_idex] = crc8(results,c_idex);
		//		debug_net_printf(results,results[1]<<8|results[2]+2,60001);
				retval = send(clientfd,results,results[1]<<8|results[2]+2,0);
				if(retval == 0 || retval == -1){
					/*socket abort*/			
				}
				close(clientfd);
				/* CLR Update Flags */
				deviceUpdate = 0x0;
			}
		break;
		}
	}
	return;

update_error:
	//debug_net_printf(results,results[1]<<8|results[2]+2,60001);
	memset(update_frames,0,sizeof(update_frames));
	for(i = 0; i < 12; i++){
		memset(&update_frames_trays[i][0],0,6);
		memset(&update_trays_stats[i][0],0,6);
	}
	retval = send(clientfd,results,results[1]<<8|results[2]+2,0);
	if(retval == 0 || retval == -1){
		/*socket abort*/			
	}
	close(clientfd);
	/* CLR Update Flags */
	deviceUpdate = 0x0;
	return;
}

/*
 *@brief: Device Software Update for sim3u146 interface board
 *@date : 2015-04-17
 *@writer:lu-ming-liang
 *@least update:2015-04-17
 */
void update_sim3u146(unsigned char dt,unsigned char *src,int fd)
{
	static unsigned char results[300];
	static int clientfd = 0;
	unsigned char  frameidex = 1, packet_num = 0x0;
	unsigned short  record_idex = 0,datlen = 0,i = 0;
	int retval = 0;

	switch(dt){
	case 3:	
		clientfd = fd;
		memset(results,0,sizeof(results));
		memset(update_status,0xEE,sizeof(update_status));
		memset(update_frames,0,sizeof(update_frames));//default Frames not update
		memset(update_frames_stats,0x0E,sizeof(update_frames_stats));//default DFU Failed
		results[0] = 0x7e;
		results[3] = 0x06;
		memcpy(&results[4],&src[4],17);
		results[21] = 0x02;//TYPE
		results[22] = src[348];//num 
		record_idex = 0; 
		/*Download file from FTP Server */
		retval = run(&src[285],&src[316],&src[21],&src[25],&src[27],src);
		for(i = 349;i < 349 + src[348]*1;i+=1){
			results[23+record_idex] = src[i];	
			results[24+record_idex] = 0x01;	//default DFU Failed 
			memcpy(&results[25+record_idex],file_version,4);
			record_idex += 6;
			frameidex = src[i];
			update_frames[frameidex-1] = 1;
		}
		
		record_idex += 23;
		results[1] = record_idex >> 8 & 0xff;
		results[2] = record_idex & 0xff; 

		/* if download Failed,repost to webmaster,update_error*/
		if(retval == 0x01){
			goto update_error;
		}

		for(i = 0; i < 12; i++){
			if(update_frames[i] > 0)
			{/*if this frame's tray need to update*/
				memset(&uart0.txBuf[i][0],0,SZ_600);
				uart0.txBuf[i][0] = 0x7e;
				uart0.txBuf[i][1] = 0x00;
				uart0.txBuf[i][2] = 0x08;
				uart0.txBuf[i][3] = 0x06;
				uart0.txBuf[i][4] = 0x01;//startup
				uart0.txBuf[i][5] = 0x02;//type:interface board
				uart0.txBuf[i][6] = 0x01;//num : 1 ge
				uart0.txBuf[i][7] = i+1;//frameidex 
				uart0.txBuf[i][8] = crc8(&uart0.txBuf[i][0],8);
				uart0.txBuf[i][9] = 0x5a;
			}		
		}
		
		if(!order_tasks_to_sim3u146_board()){	
			/* check which board repost Failed ande mark this board update Failed */
			for(i = 0; i < 12; i++){
				if(uart0.txBuf[i][3] != 0x00){
					update_frames_stats[i] = 0x01;
					memset(&uart0.txBuf[i][0],0,SZ_600);
				}
			}	
			
			/* check whether all boards DFU Failed or not ?*/
			for(i = 0;i < 12;i++){
				if((update_frames[i] == 1) && update_frames_stats[i] == 0x0E){
					break;
				}
			}		
			/* Failed all boards,upload to webmaster */	
			if(i == 12)	
				goto update_error;
		}
		
		deviceUpdate = 0x01;
		/* send start update cmd */
	break;
	case 2:
		switch(src[4]){
		case 0x01:
			/* here,we are beginning to transfer First packet*/	
			frameidex = src[7];
			packet_num = 13;//First Packet addr
			if(update_frames[frameidex-1] > 0){
				memset(&uart0.txBuf[frameidex-1][0],0,SZ_600);
				uart0.txBuf[frameidex-1][0] = 0x7e;
				uart0.txBuf[frameidex-1][1] = 0x02;
				uart0.txBuf[frameidex-1][2] = 0x0c;
				uart0.txBuf[frameidex-1][3] = 0x06;
				uart0.txBuf[frameidex-1][4] = 0x02;//transfer data packet
				uart0.txBuf[frameidex-1][5] = 0x02;//type:interface board
				uart0.txBuf[frameidex-1][6] = 0x01;//num : 1 ge
				uart0.txBuf[frameidex-1][7] = frameidex;//frameidex 
				uart0.txBuf[frameidex-1][8] = 0x00;//pan hao(zhanweifu)
				uart0.txBuf[frameidex-1][9] = 0x01;//success || Failed
				uart0.txBuf[frameidex-1][10] = packet_num >> 8 & 0xff;//xuhao1
				uart0.txBuf[frameidex-1][11] = packet_num;//xuhao1 
				memcpy(&uart0.txBuf[frameidex-1][12],&data_packet[packet_num-1][0],512);
				uart0.txBuf[frameidex-1][524] = crc8(&uart0.txBuf[frameidex-1][0],524);
				uart0.txBuf[frameidex-1][525] = 0x5a;
			}		
		
			if(!order_tasks_to_sim3u146_board()){
				/* check which board repost Failed ande mark this board update Failed */
				for(i = 0; i < 12; i++){
					if(uart0.txBuf[i][3] != 0x00){
						update_frames_stats[i] = 0x01;
						memset(&uart0.txBuf[i][0],0,SZ_600);
					}
				}	
			
				/* check whether all boards DFU Failed or not ?*/
				for(i = 0;i < 12;i++){
					if((update_frames[i] == 1) && update_frames_stats[i] == 0x0E){
						break;
					}
				}		
				/* Failed all boards,upload to webmaster */	
				if(i == 12)	
					goto update_error;
			}
		break;
		case 0x02:
			/* here,we are beginning to transfer First packet*/	
			frameidex = src[7];
			packet_num = src[11];//First Packet addr
			if(packet_num  == data_packet_num){
					if(update_frames[frameidex-1] > 0){
					memset(&uart0.txBuf[frameidex-1][0],0,SZ_600);
					uart0.txBuf[frameidex-1][0] = 0x7e;
					uart0.txBuf[frameidex-1][1] = 0x00;
					uart0.txBuf[frameidex-1][2] = 0x10;
					uart0.txBuf[frameidex-1][3] = 0x06;
					uart0.txBuf[frameidex-1][4] = 0x03;//transfer data packet
					uart0.txBuf[frameidex-1][5] = 0x02;//type:interface board
					uart0.txBuf[frameidex-1][6] = 0x01;//num : 1 ge
					
					uart0.txBuf[frameidex-1][7] = frameidex;//frameidex 
					uart0.txBuf[frameidex-1][8] = 0x00;//pan hao(zhanweifu)
					uart0.txBuf[frameidex-1][9] = 0x01;//success || Failed
					uart0.txBuf[frameidex-1][10] = 0xff;//hardware version high bit
					uart0.txBuf[frameidex-1][11] = 0xff;//hardware version low bit
					uart0.txBuf[frameidex-1][12] = 0x00;//Software version high bit
					uart0.txBuf[frameidex-1][13] = 0x01;//Software version low bit 

					uart0.txBuf[frameidex-1][14] = 0xff;//xuhao1
					uart0.txBuf[frameidex-1][15] = 0xff;//xuhao1 
					uart0.txBuf[frameidex-1][16] = crc8(&uart0.txBuf[frameidex-1][0],16);
					uart0.txBuf[frameidex-1][17] = 0x5a;
				}			
			
			}else{

				if(update_frames[frameidex-1] > 0){
					memset(&uart0.txBuf[frameidex-1][0],0,SZ_600);
					uart0.txBuf[frameidex-1][0] = 0x7e;
					uart0.txBuf[frameidex-1][1] = 0x02;
					uart0.txBuf[frameidex-1][2] = 0x0c;
					uart0.txBuf[frameidex-1][3] = 0x06;
					uart0.txBuf[frameidex-1][4] = 0x02;//transfer data packet
					uart0.txBuf[frameidex-1][5] = 0x02;//type:interface board
					uart0.txBuf[frameidex-1][6] = 0x01;//num : 1 ge
					uart0.txBuf[frameidex-1][7] = frameidex;//frameidex 
					uart0.txBuf[frameidex-1][8] = 0x00;//pan hao(zhanweifu)
					uart0.txBuf[frameidex-1][9] = 0x01;//success || Failed
					uart0.txBuf[frameidex-1][10] = packet_num >> 8 & 0xff;//xuhao1
					uart0.txBuf[frameidex-1][11] = packet_num + 1;//xuhao1 
					memcpy(&uart0.txBuf[frameidex-1][12],&data_packet[packet_num][0],512);
					uart0.txBuf[frameidex-1][524] = crc8(&uart0.txBuf[frameidex-1][0],524);
					uart0.txBuf[frameidex-1][525] = 0x5a;
				}		
			}

			if(!order_tasks_to_sim3u146_board()){
				/* check which board repost Failed ande mark this board update Failed */
				for(i = 0; i < 12; i++){
					if(uart0.txBuf[i][3] != 0x00){
						update_frames_stats[i] = 0x01;
						memset(&uart0.txBuf[i][0],0,SZ_600);
					}
				}	
			
				/* check whether all boards DFU Failed or not ?*/
				for(i = 0;i < 12;i++){
					if((update_frames[i] == 1) && update_frames_stats[i] == 0x0E){
						break;
					}
				}		
				/* Failed all boards,upload to webmaster */	
				if(i == 12)	
					goto update_error;
			}
			
		break;
		case 0x03:
			/* restart sim3u146 boards*/
			frameidex = src[7];
			update_frames_stats[frameidex-1] = src[9];
			
			for(i = 23; i < results[2];i+= 6){
				if(results[i] == frameidex){
					results[i+1] = src[9];		
					break;
				}
			}

			update_status[frameidex-1] = 0x01;

			for(i = 0; i < 12; i++){
				if((update_frames[i] == 1) && update_frames_stats[i] == 0x0E){
					break;
				}
			}

			if(i == 12){
			/* i== 12,it means all interface boards that needed update
			 * finished*/	
				datlen = results[2];
				results[datlen] = crc8(results,datlen);
				results[datlen+1] = 0x5a;
				//here debug
			//	debug_net_printf(results,results[2]+2,60001);
				retval = send(clientfd,results,results[1]<<8|results[2]+2,0);
				if(retval == 0 || retval == -1){	
				/*socket abort*/	
				}
				close(clientfd);
				/* CLR Update Flags */
				deviceUpdate = 0x00;
			}

		break;
		}//endof switch(src[4])
	}

	return ;	

update_error:
	datlen = results[2];
	results[datlen] = crc8(results,datlen);
	results[datlen+1] = 0x5a;
	//here debug
//	debug_net_printf(results,results[2]+2,60001);
	retval = send(clientfd,results,results[1]<<8|results[2]+2,0);
	if(retval == 0 || retval == -1){	
		/*socket abort*/	
	}
	close(clientfd);
	/* CLR Update Flags */
	deviceUpdate = 0x0;
	return;
}


void update_s3c44b0x(unsigned char *src,int fd)
{
	unsigned long ofs,packetidex;
	int i,rfd,ofd,bs,start_addr,end_addr;
	unsigned char oobbuf[16];
	struct mtd_oob_buf oob = {0,16,oobbuf};
	mtd_info_t meminfo;
	int retval = 0;
	unsigned char results[50];
	unsigned char buf[BUF_SIZE];
	unsigned char readbuf[BUF_SIZE];
	
	memset(results,0,sizeof(results));
	results[0] = 0x7e;
	results[1] = 0x00;
	results[2] = 0x1e;
	results[3] = 0x06;
	memcpy(&results[4],&src[4],17);
	results[21] = 0x01;//TYPE
	results[22] = 0x01;//num
	results[23] = 0xff;//zhukong
	results[24] = 0x00;//zhanweifu
	results[25] = 0x01;//success/fail
		
	/* Download files from FTP Server*/
	retval = run(&src[285],&src[316],&src[21],&src[25],&src[27],src);
	if(retval == 0x1){
		/* download fail*/
		goto update_error;
	}

	memcpy(&results[26],file_version,4);

	/* eraseall this section */
	if(	system("/bin/eraseall /dev/mtd0") == -1){
		/*erase Failed*/
		goto update_error;
	}

	/* Open MTD device */
	if((rfd = open("/dev/mtd0",O_RDWR)) == -1){
		//perror("can't open mtd0");
		goto update_error;
	}

	/* Fill in MTD device capability structure */   
	if (ioctl(rfd, MEMGETINFO, &meminfo) != 0){
		//perror("MEMGETINFO");
		goto update_error;
	}

#if 0	
	/* Make sure device page sizes are valid */
	if (!(meminfo.oobsize == 16 && meminfo.oobblock == 512) &&
	    !(meminfo.oobsize == 8 && meminfo.oobblock == 256)){
		//printf("Unknown flash (not normal NAND)\n");
		goto update_error;
	}
#endif 


	/* Initialize start/end addresses and block size */
	start_addr = 0;
	end_addr = meminfo.size;
	/* bs is short for pagesize = 512bytes */	
	bs = 2048; /*here,should be pagesize = 2048*/
	packetidex = 0;	
	for(ofs = start_addr; ofs < end_addr ; ofs += bs){
		
		memset(buf,0xff,BUF_SIZE);
		memset(oobbuf,0xff,16);
   		if((retval = read(data_sock, buf, BUF_SIZE)) > 0){
			
			/* 1-1-1 :write_page_with_ecc */
			if (pwrite(rfd, buf, bs, ofs) != bs) {
				retval = 1;
				break;
			}

			/* 2-1-1 :calculate_ecc and write_oob  */
			oob.start = ofs;
			nand_calculate_ecc(&buf[0],oobbuf);	
			nand_calculate_ecc(&buf[256],oobbuf);	
			if (ioctl(rfd, MEMWRITEOOB, &oob) != 0) {
				retval = 1;
				break;
			}

			/* 3-1-1 : read data and checkout write success or not */
			if (pread(rfd, readbuf, bs, ofs) != bs) {
				retval = 1;
				close(rfd);
			}
			for(i = 0;i < BUF_SIZE;i++){
				if(readbuf[i] != buf[i])
					break;
			}
			if(i != BUF_SIZE){
				retval = 1;
				break;
			}

			/* 4-1-1 : dat pack num*/
			//packetidex++;	
			retval = 0;

		}else{
		
			/* update finished */
			retval = 0;
			break;
		}

	}

	if(retval == 1){
		/* write Failed*/
		results[25] = 0x01;
	}else{
		results[25] = 0x00;
	}

	results[30] = crc8(results,30);
	results[31] = 0x5a;
	retval = send(fd,results,results[1]<<8|results[2]+2,0);
	if(retval == 0 || retval == -1){
		/*socket abort*/
	}

	/* close file discription */
	close(fd);
	close(rfd);
	close(data_sock);

	/* restart system */
	system("/bin/reboot");

	/* Exit happy*/
	return;

update_error:
	results[25] = 0x01;
	results[30] = crc8(results,30);
	results[31] = 0x5a;
	retval = send(fd,results,results[1]<<8|results[2]+2,0);
	if(retval == 0 || retval == -1){
		/*socket abort*/
	}else{
		close(fd);
	}
	close(rfd);
	close(data_sock);
	return;
}

